<?php


namespace App\Service\common;


use App\Common\Res;
use App\Common\StringUtils;
use App\Constants\ErrorCode;
use App\Model\Avatar;
use App\Model\File;
use HyperfException\Json;
use OSS\Core\OssException;
use OSS\Http\RequestCore_Exception;
use OSS\OssClient;
use Hyperf\Config\Annotation\Value;

class uploadService
{
    use Res, StringUtils;

    /**
     * @Value("commonset.aliyun.oss.accessKeyId")
     */
    protected $accessKeyId;

    /**
     * @Value("commonset.aliyun.oss.accessKeySecret")
     */
    protected $accessKeySecret;

    /**
     * @Value("commonset.aliyun.oss.endpoint")
     */
    protected $endpoint;

    /**
     * @Value("commonset.aliyun.oss.bucket")
     */
    protected $bucket;

    /**
     * @Value("commonset.avatarDir")
     */
    protected $avatarDir;

    /**
     * @Value("commonset.localAvatarDir")
     */
    protected $localAvatarDir;

    /**
     * @Value("commonset.chatDir")
     */
    protected $chatDir;

    /**
     * @Value("commonset.localChatDir")
     */
    protected $localChatDir;

    /**
     * @Value("commonset.pathType")
     */
    protected $pathType;

    /**
     * @Value("commonset.hostUrl")
     */
    protected $hostUrl;

    /**
     * oss上传
     * @param object $file
     * @param array $params
     * @return array
     * @throws RequestCore_Exception
     */
    public function uploadAvatarOss(object $file, array $params): array
    {
        $params['name'] = $file->getClientFilename();
        $params['filePath'] = $file->getPathname();
        // 由于 Swoole 上传文件的 tmp_name 并没有保持文件原名，所以这个方法已重写为获取原文件名的后缀名
        $params['extension'] = $file->getExtension();
        $params['size'] = $file->getSize();
        $accessKeyId = $this->accessKeyId;
        $accessKeySecret = $this->accessKeySecret;
        $endpoint = $this->endpoint;
        $bucket = $this->bucket;
        $oss_key = sha1(date('YmdHis', time()) . uniqid());
        $object = date('Ymd', time()) . '/' . $params['device_id'] . '/avatar/' . $oss_key . '.' . $params['extension'];
        $filePath = $params['filePath'];
        try {
            $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
            $res = $ossClient->uploadFile($bucket, $object, $filePath);
            $localPath = $endpoint . '/' . $object;
            return $this->Success("头像上传成功", ['path' => $localPath]);
        } catch (OssException $e) {
            return $this->Error(ErrorCode::ERROR, "头像上传失败");
        }
    }

    /**
     * 上传文件到服务器
     * @param array $params
     * @return array
     */
    public function uploadAvatar(object $file, array $params): array
    {
        $day = date('Ymd', time()) . '/';
        try {
            $fileHash = hash_file('sha256', $file->getPathname());
            if (!empty($fileHash)) {
                $avatar = Avatar::where(['file_hash' => $fileHash])->first();
                if (!empty($avatar)) {
                    return $this->Success("头像上传成功", ['path' => $avatar['path']]);
                } else {
                    $params['name'] = $file->getClientFilename();
                    $params['filePath'] = $file->getPathname();
                    $params['size'] = $file->getSize();
                    // 该路径为上传文件的临时路径
                    $params['path'] = $file->getPath();
                    // 由于 Swoole 上传文件的 tmp_name 并没有保持文件原名，所以这个方法已重写为获取原文件名的后缀名
                    $params['extension'] = $file->getExtension();
                    $this->makeDirectory($this->avatarDir. $day);
                    $oss_key = sha1(date('YmdHis', time()) . uniqid());
                    $filePath = $this->avatarDir . $day . $oss_key . '.' . $params['extension'];
                    /*相对路径*/
                    $localPath = $this->localAvatarDir . $day . $oss_key . '.' . $params['extension'];
                    Avatar::create([
                        'extension' => $params['extension'],
                        'name' => $params['name'],
                        'oss_key' => $oss_key,
                        'path' => $localPath,
                        'dir' => $this->localAvatarDir .$day. date('Ymd', time()) . '/',
                        'create_time' => time(),
                        'size' => $params['size'],
                        'path_type' => $this->pathType,
                        'file_hash' => $fileHash,
                    ]);
                    $file->moveTo($filePath);
                    if ($file->isMoved()) {
                        return $this->Success("头像上传成功", ['path' => $localPath]);
                    } else {
                        return $this->Error(ErrorCode::ERROR, "头像上传失败");
                    }
                }
            } else {
                return $this->Error(ErrorCode::ERROR, "头像上传失败");
            }
        } catch (\Throwable $ex) {
            return $this->Error(ErrorCode::ERROR, "头像上传失败");
        }
    }


    /**
     * oss上传聊天文件
     * @param object $file
     * @param array $params
     * @return array
     * @throws RequestCore_Exception
     */
    public function uploadChatFileOss(object $file, array $params): array
    {
        $day = date('Ymd', time()) . '/';
        $params['name'] = $file->getClientFilename();
        $params['filePath'] = $file->getPathname();
        // 由于 Swoole 上传文件的 tmp_name 并没有保持文件原名，所以这个方法已重写为获取原文件名的后缀名
        $params['extension'] = $file->getExtension();
        $params['size'] = $file->getSize();
        $accessKeyId = $this->accessKeyId;
        $accessKeySecret = $this->accessKeySecret;
        $endpoint = $this->endpoint;
        $bucket = $this->bucket;
        $oss_key = sha1(date('YmdHis', time()) . uniqid());
        $object = date('Ymd', time()) . '/' . $params['device_id'] . '/chat/' . $oss_key . '.' . $params['extension'];
        $filePath = $params['filePath'];
        try {
            $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
            $res = $ossClient->uploadFile($bucket, $object, $filePath);
            $localPath = $endpoint . '/' . $object;
            $data['path'] = $localPath;
            $data['extension'] = $params['extension'];
            $data['name'] = $params['name'];
            $data['oss_key'] = $oss_key;
            $data['dir'] = $object;
            $data['create_time'] = time();
            $data['size'] = $params['size'];
            $data['path_type'] = $this->pathType;
            $attach = File::create($data);
            return $this->Success("图片上传成功", ['id' => $attach['id'], 'path' => $localPath]);
        } catch (OssException $e) {
            return $this->Error(ErrorCode::ERROR, "图片上传失败");
        }
    }

    /**
     * 上传文件到服务器
     * @param array $params
     * @return array
     */
    public function uploadChatFile(object $file, array $params): array
    {
        $day = date('Ymd', time()) . '/';
        try {
            $params['name'] = $file->getClientFilename();
            $params['filePath'] = $file->getPathname();
            $params['size'] = $file->getSize();
            // 该路径为上传文件的临时路径
            $params['path'] = $file->getPath();
            // 由于 Swoole 上传文件的 tmp_name 并没有保持文件原名，所以这个方法已重写为获取原文件名的后缀名
            $params['extension'] = $file->getExtension();
            $this->makeDirectory($this->chatDir. $day);
            $oss_key = sha1(date('YmdHis', time()) . uniqid());
            $filePath = $this->chatDir . $day . $oss_key . '.' . $params['extension'];
            /*相对路径*/
            $localPath = $this->localChatDir . $day . $oss_key . '.' . $params['extension'];
            $file->moveTo($filePath);
            if ($file->isMoved()) {
                $data['extension'] = $params['extension'];
                $data['name'] = $params['name'];
                $data['oss_key'] = $oss_key;
                $data['path'] = $localPath;
                $data['dir'] = $this->chatDir;
                $data['create_time'] = time();
                $data['size'] = $params['size'];
                $data['path_type'] = $this->pathType;
                $attach = File::create($data);
                $fullPath = $this->hostUrl . $localPath;
                $path = $localPath;
                return $this->Success("图片上传成功", ['id' => $attach['id'], 'path' => $path, 'fullPath' => $fullPath]);
            } else {
                return $this->Error(ErrorCode::ERROR, "图片上传失败");
            }
        } catch (\Throwable $ex) {
            return $this->Error(ErrorCode::ERROR, "图片上传失败");
        }
    }


}